<template>
	<view class="w-p-100 flex flex-center flex-column">
		<view class="w-80 h-80 flex flex-center bg-blue round-circle" v-if="current==1" @click="onStart">
			<text class="iconfont icon-luyin1 text-white fs-40"></text>
		</view>
		<view v-if="current==2" class="flex flex-column flex-center gap-20">
			<text class="fs-26 fw-600">{{ $tool.formatSecondsToMinutes(duration)}}</text>
			<view class="h-30">
				<y-voice-ani></y-voice-ani>
			</view>
			<button class="fs-14 bg-blue text-white " @click="stop">完成录制</button>
		</view>
		<view class="flex flex-y-center gap-20" v-if="current==3">
			<view class="w-60 h-60 flex  flex-center bg-21 round-circle" @click="current=1">
				<text class="iconfont icon-fanhui  fs-25"></text>
			</view>
			<view class="w-80 h-80 flex  flex-center bg-blue round-circle" @click="play">
				<text class="iconfont  text-white fs-40" :class="audioStatus?'icon-zanting1':'icon-bofang'"></text>
			</view>
			<view class="w-60 h-60 flex  flex-center bg-green round-circle" @click="onStart">
				<text class="iconfont icon-zhongshi1 text-white fs-25"></text>
			</view>
		</view>

		<view class='border-blue p-8 mt-20 round-10 flex flex-y-center pr-16'
			style='border-style: dashed;border-width: 0.5px;'>
			<view class='w-60 h-60 round-8 flex flex-center'>
				<text class='iconfont icon-shangchuanwenjian  fs-25'></text>
			</view>
			<!-- #ifdef MP-WEIXIN -->
			<view class="flex flex-column gap-8 ml-8" @click='chooseMessageFile'>
				<text class='  fs-16'>从微信中选择</text>
				<text class='fs-12 text-999'>格式要求:mp3 m4a wav</text>
			</view>
			<!-- #endif -->
			<!-- #ifdef H5 -->
			<view class="flex flex-column gap-8 ml-8" @click='chooseFile'>
				<text class='  fs-16'>从文件中选择</text>
				<text class='fs-12 text-grey-1'>格式要求:mp3 m4a wav</text>
			</view>
			<!-- #endif -->
		</view>
	</view>
</template>

<script setup>
	import { ref, onMounted, onUnmounted } from 'vue';
	import { $tool } from '@/utils';


	const emit = defineEmits(['success']);
	const props = defineProps({
		maxDuration: {
			type: Number,
			default: 30
		}
	})

	//当前步骤
	const current = ref(1)
	//录音时长
	const duration = ref(0)
	let isUserMedia = false;
	//H5音频对象 
	let mediaRecorder;
	let audio;
	//h5 麦克风是否可用
	const h5RecorderState = ref(true);
	const recorderState = ref(false);
	let mediaStream;

	let startTime;
	let startTimeEr;

	let recordedBlobs = [];
	let innerAudioContext = uni.createInnerAudioContext();
	const audioStatus = ref(false)


	// #ifndef H5
	const recorderManager = uni.getRecorderManager();
	// #endif

	//组件挂载
	onMounted(() => {
		// #ifdef H5
		checkUserMedia()
		// #endif
		initAudio()

		// #ifndef H5
		recorderManager.onStop((res) => {
			clearInterval(startTimeEr);
			recorderState.value = false;
			innerAudioContext.src = res.tempFilePath
			emit('success', { url: res.tempFilePath, duration: duration.value })
		});
		recorderManager.onError((err) => {
			uni.showModal({
				title: '录制失败:',
				content: err.errMsg
			})
			current.value = 1
			clearInterval(startTimeEr);
			recorderState.value = false;
		});
		recorderManager.onStart(() => {
			current.value = 2
		})
		// #endif
	})

	//开始录音
	const onStart = () => {
		duration.value = 0;
		// #ifdef H5
		if (!isUserMedia) {
			$tool.toast('请允许使用麦克风');
			return;
		}
		navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
			current.value = 2
			recordedBlobs = []
			mediaStream = stream
			mediaRecorder = new MediaRecorder(stream, {
				audioBitsPerSecond: 128000
			})
			mediaRecorder.ondataavailable = (event) => {
				recorderState.value = true;
				recordedBlobs.push(event.data)
			}
			mediaRecorder.onstop = () => {
				clearInterval(startTimeEr);
				recorderState.value = false;
				const file = new File(recordedBlobs, getRandomString(10) +
				'recorder.mp3', { type: 'audio/mp3' });
				const url = URL.createObjectURL(file);
				innerAudioContext.src = url
				emit('success', { url: url, duration: duration.value, file: file })
			}
			mediaRecorder.start()
			startTime = new Date().getTime();
			startTimeEr = setInterval(() => {
				duration.value = Math.floor((new Date().getTime() - startTime) / 1000);
				if (props.maxDuration && duration.value >= props.maxDuration) {
					stop();
				}
			}, 1000)
			recorderState.value = true;
		}).catch(err => {
			let content = '';
			switch (err.name) {
				case 'NotAllowedError':
					content = '当前浏览器不支持录音，请更换浏览器或在微信中打开。';
					break;
				case 'NotReadableError':
					content = '麦克风权限被拒绝，请刷新页面后授权麦克风权限。';
					break
				default:
					content = '未知错误，请刷新页面重试：' + JSON.stringify(err);
					break
			}
			uni.showModal({
				content: content,
				success: (res) => {
					if (res.confirm) {
						uni.navigateBack()
					}
				}
			})
		})
		// #endif

		// #ifdef MP-WEIXIN
		startTime = new Date().getTime();
		startTimeEr = setInterval(() => {
			duration.value = Math.floor((new Date().getTime() - startTime) / 1000);
			if (props.maxDuration && duration.value >= props.maxDuration) {
				stop();
			}
		}, 1000)
		recorderState.value = true;
		let options = {
			duration: 600000,
			format: 'mp3',
		};
		if (props.maxDuration) {
			options.duration = props.maxDuration * 1000;
		}
		recorderManager.start(options);
		// #endif
	}

	//停止录音
	const stop = () => {
		current.value = 3
		// #ifdef H5
		mediaRecorder.stop()
		mediaStream.getTracks().forEach((track) => {
			track.stop()
		})
		// #endif
		// #ifndef H5
		recorderManager.stop();
		// #endif
	}



	const initAudio = () => {
		innerAudioContext.onCanplay(() => {
			if (innerAudioContext.duration != Infinity) {
				duration.value = Math.ceil(innerAudioContext.duration)
			}
		})
		innerAudioContext.onPlay(() => {
			audioStatus.value = true
		})
		innerAudioContext.onStop(() => {
			audioStatus.value = false
		})
		innerAudioContext.onPause(() => {
			audioStatus.value = false
		})

	}

	const play = () => {
		if (audioStatus.value == false) {
			innerAudioContext.play()
		} else {
			innerAudioContext.pause()
		}
	}


	// #ifdef H5
	//验证麦克风是否可用
	const checkUserMedia = () => {
		if (location.protocol !== 'https:') {
			uni.showModal({
				content: '录音只能在HTTPS环境中使用'
			})
			return h5RecorderState.value = false;
		}
		if (!navigator.mediaDevices || !window.MediaRecorder) {
			uni.showModal({
				content: '当前浏览器不支持录音，请更换浏览器或在微信中打开。'
			})
			return h5RecorderState.value = false;
		}
		audio = document.createElement('audio')
		navigator.mediaDevices.getUserMedia({ audio: true })
			.then(stream => {
				isUserMedia = true;
				stream.getTracks().forEach((track) => {
					track.stop()
				})
			})
			.catch(error => {
				uni.showModal({
					content: JSON.stringify(error),
				})
			});
	}
	// #endif



	const chooseMessageFile = () => {
		wx.chooseMessageFile({
			count: 1,
			type: 'file',
			extension: ['mp3', 'wav', 'm4a', 'webm'],
			success: (res) => {
				const file = res.tempFiles[0];
				innerAudioContext.src = file.path
				current.value = 3
				setTimeout(() => {
					emit('success', { url: file.path, duration: duration.value, file: file })
				}, 300)
			},
			fail: (err) => {
				console.log('err', err)
			}
		})
	}
	const chooseFile = () => {
		uni.chooseFile({
			count: 1,
			extension: ['mp3', 'wav', 'm4a', 'webm'],
			success: (res) => {
				innerAudioContext.src = res.tempFilePaths[0]
				emit('success', {
					url: res.tempFilePaths[0],
					file: res.tempFiles[0],
					duration: duration
						.value
				})
				current.value = 3
			}
		});
	}

	onUnmounted(() => {
		if (innerAudioContext) {
			try {
				innerAudioContext.pause();
				innerAudioContext.destroy()
			} catch (e) {}
		}
	})

	const getRandomString = (length) => {
		var result = '';
		var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
		var charactersLength = characters.length;
		for (var i = 0; i < length; i++) {
			result += characters.charAt(Math.floor(Math.random() * charactersLength));
		}
		return result;
	}
</script>

<style>
	.fs-40 {
		font-size: 40px;
	}
</style>